#!/usr/bin/env python

import vt100
import random
import time
import sys, os
import threading

row = 20
col = 12
x = 0
y = 3
i = random.randint(0, 6)
w = 0
tetris = []
accumulation = []
string = 's'
flag = True


def tetrisList(num):
    '''
    7种基本方块数组
    '''

    if num == 0:
        tetris = [[0,0], [1,0], [0,-1], [1,1]]
    elif num == 1:
        tetris = [[0,0], [0,1], [1,0], [1,-1]]
    elif num == 2:
        tetris = [[0,0], [0,1], [0,-1], [1,-1]]
    elif num == 3:
        tetris = [[0,0], [0,1], [0,-1], [-1,-1]]
    elif num == 4:
        tetris = [[0,0], [0,1], [0,-1], [1,-1]]
    elif num == 5:
        tetris = [[0,0], [0,-1], [0,1], [0,2]]
    else:
        tetris = [[0,0], [-1,0], [1,0], [2,0]]

    return tetris


def whirl(l, count):
    '''
    方块旋转
    '''
    lw = l.copy()
    for i in range(count):
        for m, a in enumerate(lw):
            x = a[0]
            lw[m][0] = a[1]
            lw[m][1] = -x

    return lw


def init():
    '''
    初始化游戏
    '''

    global tetris 

    #获取方块所有数组
    for i in range(7):
        tetris.append([])
        for k in range(4):

            tetris[i].append(whirl(tetrisList(i), k))
    vt100.cursor('hide')
    vt100.gotoxy(1, 1, '')
    os.system('stty -echo -icanon')


def show_bg():
    '''
    打印游戏画板
    '''

    for i in range(row):
        for j in range(col):
            d = ' '
            if i == 0 or i == row - 1 or j == 0 or j == col - 1:
                d = "#"
            vt100.gotoxy(i + 1, j + 1, d)


def drawTetris(l, string):
    for j in l:
        xt = x + j[0]
        yt = y + j[1]
        vt100.gotoxy(yt, xt, string)


def drawAccum(l,string):
    for j in l:
        vt100.gotoxy(j[1], j[0], string)


def move(string):
    global x, y, w
    if string == 'a':
        x -= 1
    elif string == 'd':
        x += 1
    elif string == 's':
        y += 1
    elif string == 'w':
        w += 1
        if w == 4:
            w = 0


def collision():
    global x, y, w
    for j in range(4):
        xc = tetris[i][w][j][0] + x
        yc = tetris[i][w][j][1] + y
        if ([xc, yc] in accumulation or yc >= row or xc < 2 or xc > col - 1):
            return True
    return False


def handleCollision(string):
    global x, y, i
    if string == 'a':
         x += 1
    elif string == 'd':
        x -= 1
    elif string == 'w':
        w -= 1
        if w == -1:
            w = 3
    else :
        y -= 1
        addAccumulation()

        x = col // 2
        y = 3
        vt100.gotoxy(y, x, '')
        i = random.randint(0, 6)
    eliminate()
    isGameOver()


def addAccumulation():
    global accumulation
    for j in range(4):
        xa = tetris[i][w][j][0] + x
        ya = tetris[i][w][j][1] + y
        accumulation.append([xa, ya])


def eliminate():
    global accumulation
    for j in range(row, 1, -1):
        for k in range(2, col):
            if [k, j] not in accumulation:
                break
            if k == col - 1:
                for k in range(2, col):
                    accumulation.remove([k, j])
                for m in accumulation:
                    if m[1] < j:
                        m[1] += 1
                show_bg()
                drawTetris(tetris[i][w], '{')
                drawAccum(accumulation, '{')
                eliminate()


def isGameOver():
    global flag
    if collision():
        for j in range(4):
            if tetris[i][w][j][1] < 2:
                gameOver()


def gameOver():
    global flag
    flag = False
    vt100.cursor('display')
    vt100.gotoxy(row // 2, col // 4, 'GAME OVER')
    os.system('stty echo')


def operate():
    while flag:
        key = sys.stdin.read(1)
        if key == 'q':
            gameOver()
            break
        if key in ['a', 'w', 's', 'd']:
            drawTetris(tetris[i][w], ' ')
            move(key)
            if collision():
                handleCollision(key)
            drawTetris(tetris[i][w], '{')
        time.sleep(0.1)


def tetrisRun():
    global y
    init()
    show_bg()
    while flag:
        drawTetris(tetris[i][w]," ")
        y += 1
        if collision():
            handleCollision(string)
        drawTetris(tetris[i][w], '{')
        drawAccum(accumulation, '{')
        time.sleep(1)


def TetrisStart():
    threads = []
    t1 = threading.Thread(target = tetrisRun)
    threads.append(t1)
    t2 = threading.Thread(target = operate)
    threads.append(t2)
    for t in threads:
        t.setDaemon(True)
        t.start()
    while flag:
        time.sleep(4)

TetrisStart()


